<script setup lang="ts">
import { computed, ref, watch, reactive, watchEffect } from 'vue';

let firstName = ref(null)
let lastName = ref(null)

// let name = computed(() => {
//   return firstName.value + '-' + lastName.value
// })
let name = computed({
  set() {
    firstName.value + '-' + lastName.value
  },
  get() {
    return firstName.value + '-' + lastName.value
  }
})

let message = ref<number>(0)
let message2 = ref<string>('')
let message3 = ref({
  nav: {
    bar: {
      name: '张三'
    }
  }
})

let message4 = reactive({
  nav: {
    bar: {
      name: '张三'
    }
  }
})

let message5 = reactive({
  nav: '导航一',
  bar: '导航二'
})

// watch(message, (newVal, oldVal) => {
//   console.log('新的 --->', newVal);
//   console.log('老的 --->', oldVal);
// })
watch([message, message2], (newVal, oldVal) => {
  console.log('新的 --->', newVal);
  console.log('老的 --->', oldVal);
})

watch(message3, (newVal, oldVal) => {
  console.log('新的 --->', newVal);
  console.log('老的 --->', oldVal);
}, {
  deep: true                             // 深度监听 , 如果不加，在ref响应属性下，监听不到嵌套属性
})

watch(message4, (newVal, oldVal) => {      
  console.log('新的 --->', newVal);
  console.log('老的 --->', oldVal);
}, 
// {deep:true}                      // 在reactive下的属性，不加 deep 也能监听到
)

// watch(message5, (newVal, oldVal) => {        // 监听整个
//   console.log('新的 --->', newVal);
//   console.log('老的 --->', oldVal);
// })

watch(() => message5.nav, (newVal, oldVal) => {        // 监听其中的单个
  console.log('新的 --->', newVal);
  console.log('老的 --->', oldVal);
})

let msg = ref<string>('飞机')
let msg2 = ref<string>('飞机杯子')
// 高级监听
// watchEffect(() => {
//   console.log("msg==>", msg.value);     // 会自动监听,写哪个值就监听哪个
// })
// watchEffect((oninvalidate) => {
//   console.log("msg==>", msg.value);     // 会自动监听
//   oninvalidate(() => {                // 最先调用，在操作监听的值之前操作
//     console.log("before");
//   })
//   console.log("msg2==>", msg2.value);     // 会自动监听
// })
const stop = watchEffect((oninvalidate) => {         // 会返回一个stop 函数， 调用一下，可以停止监听
  oninvalidate(() => {                // 最先调用，在操作监听的值之前操作
    console.log("before");
  })
  console.log("msg2==>", msg2.value);     // 会自动监听
})

const stopWatch = () => stop()

watchEffect((oninvalidate) => { 
  let inp: HTMLInputElement = document.querySelector("#inp") as HTMLInputElement     // inp 可能为null,  ts中用 as 来断言

  console.log(inp);
  
  oninvalidate(() => {               
    console.log("before");
  })
}, {
  // flush 指刷新时机，可选3个值 pre: 组件更新前执行， sync: 强制同步触发，  post: 组件更新后执行
  flush: "post",    // flush 配置为post 是让页面一加载(更新)就可以获取 dom 元素，否则在上面的 inp 为null
  onTrigger: (e) => {   // onTrigger 是用来调试的， 会调出 vuetool插件
    console.log(e);
  }
})
</script>

<template>
  <div>
    <input v-model="firstName" type="text">
    <input v-model="lastName" type="text">

    <div>
      {{name}}
    </div>
    
    <input v-model="message" type="text">
    <input v-model="message2" type="text">
    <input v-model="message3.nav.bar.name" type="text">
    <input v-model="message4.nav.bar.name" type="text">
    <br>
    <input v-model="message5.nav" type="text">
    <input v-model="message5.bar" type="text">
    <br>
    <input id="inp" v-model="msg" type="text">
    <input v-model="msg2" type="text">
    <button @click="stopWatch">停止监听</button>
  </div>
</template>

<style>
</style>